package com.ricchieri.service;

import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.transaction.annotation.Transactional;

import com.ricchieri.common.BusinessSettings;
import com.ricchieri.common.CustomAuthenticationToken;
import com.ricchieri.dao.interf.IReservationDao;
import com.ricchieri.filter.EmailTemplateFilter;
import com.ricchieri.filter.ReservationFilter;
import com.ricchieri.model.EmailTemplate;
import com.ricchieri.model.EmailToSend;
import com.ricchieri.model.Reservation;
import com.ricchieri.model.ScheduleCharter;
import com.ricchieri.model.User;
import com.ricchieri.service.interf.IEmailTemplateService;
import com.ricchieri.service.interf.IEmailToSendService;
import com.ricchieri.service.interf.IReservationService;
import com.ricchieri.util.DateUtil;
import com.ricchieri.util.FacesUtil;

@Transactional(readOnly = true)
public class ReservationService implements IReservationService, Serializable {
	private static final long serialVersionUID = -2908945723953647148L;
	
	IReservationDao reservationDao;
	
	IEmailToSendService emailToSendService;
	IEmailTemplateService emailTemplateService;
	private EmailTemplate emailTemplateWarning;
	
	@Override
	@Transactional(readOnly = true)
	public List<Reservation> getAllReservation() {
		ReservationFilter reservationFilter = new ReservationFilter();
		return reservationDao.getAllReservation(reservationFilter);
	}
	
	@Override
	@Transactional(readOnly = true)
	public List<Reservation> getAllReservationByFilter(ReservationFilter reservationFilter) {
		return reservationDao.getAllReservation(reservationFilter);
	}
	

	public IReservationDao getReservationDao() {
		return reservationDao;
	}

	public void setReservationDao(IReservationDao reservationDao) {
		this.reservationDao = reservationDao;
	}
	
	@Override
	@Transactional(readOnly = false)
	public void addReservation(Reservation reservation) {
		User currentUser = ((CustomAuthenticationToken)SecurityContextHolder.getContext().getAuthentication()).getUser();
		reservation.setOperator(currentUser);
		reservation.getScheduleCharter().getReservation().add(reservation);
		reservationDao.add(reservation);
		this.createReservationEmail(reservation, BusinessSettings.EMAIL_TEMPLATE_RESERVATION);
	}

	@Override
	public int getAllReservationCountByFilter(
			ReservationFilter reservationFilter) {
		return reservationDao.getAllReservationCountByFilter(reservationFilter);
	}

	@Override
	public Reservation getReservationById(ReservationFilter reservationFilter) {
		return reservationDao.getReservationById(reservationFilter);
	}

	@Override
	public List<Reservation> getAllReservationPaginatedByFilter(
			ReservationFilter reservationFilter, int startRecord) {
		return reservationDao.getAllReservationPaginatedByFilter(reservationFilter, startRecord);
	}

	@Override
	@Transactional(readOnly = false)
	public void updateReservation(Reservation reservation, Boolean sendMail) {
		User currentUser = ((CustomAuthenticationToken)SecurityContextHolder.getContext().getAuthentication()).getUser();
		reservation.setOperator(currentUser);
		reservationDao.update(reservation);
		
		if(sendMail) {
			this.createReservationEmail(reservation, BusinessSettings.EMAIL_TEMPLATE_RESERVATION_UPDATED);
		}
	}
	
	
	private void createReservationEmail(Reservation reservation, String emailTemplateType) {		
		EmailTemplateFilter emailTemplateFilter = new EmailTemplateFilter();
		emailTemplateFilter.setEmailTemplateTypeDescription(emailTemplateType);
		EmailTemplate emailTemplate = emailTemplateService.getEmailTemplateByFilter(emailTemplateFilter);
		
		if(emailTemplate != null && reservation.getUser().getDefaultEmail() != null) {
			EmailToSend emailToSend = new EmailToSend();
			
			String content = emailTemplate.getTemplate();
			String origenTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_ORIGIN);
			String destinyTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_DESTINY);
			String reservationDateTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_RESERVATION_DATE);
			String fullNameTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_FULLNAME);
			String reservationNumberTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_RESERVATION_NUMBER);
			String tripDateTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_TRAVEL_DATE);
			String priceTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_TRAVEL_PRICE);
			String operatorTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_OPERATOR);
			String upOnTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_UP_ON);
			String downOnTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_DOWN_ON);
			
			String dateTravel =  DateUtil.formatDate(reservation.getScheduleCharter().getSchedule().getDate());
			dateTravel = dateTravel.concat(" ").concat(DateUtil.formatTime(reservation.getScheduleCharter().getSchedule().getTime()));
			
			content = content.replace("{".concat(origenTag).concat("}"), FacesUtil.getMessage(reservation.getScheduleCharter().getTrip().getPlaceOrigin().getDescription()));
			content = content.replace("{".concat(destinyTag).concat("}"), FacesUtil.getMessage(reservation.getScheduleCharter().getTrip().getPlaceDestiny().getDescription()));
			content = content.replace("{".concat(reservationDateTag).concat("}"), DateUtil.formatDateTime(reservation.getReservationDate()));
			content = content.replace("{".concat(fullNameTag).concat("}"), reservation.getUser().getFullName());
			content = content.replace("{".concat(reservationNumberTag).concat("}"), String.valueOf(reservation.getId()));
			content = content.replace("{".concat(tripDateTag).concat("}"), dateTravel);
			content = content.replace("{".concat(priceTag).concat("}"), String.valueOf(reservation.getCost()));
			content = content.replace("{".concat(operatorTag).concat("}"), String.valueOf(reservation.getOperator().getFirstName()));
			
			content = content.replace("{".concat(upOnTag).concat("}"), reservation.getUpOn());
			content = content.replace("{".concat(downOnTag).concat("}"), reservation.getDownOn());
					
			emailToSend.setUser(reservation.getUser());
			emailToSend.setMessageContent(content);
			emailToSend.setEmailToSendType(emailTemplate.getEmailToSendType());
			emailToSend.setSubjectContent(emailTemplate.getSubject());
			
			emailToSendService.add(emailToSend);
		}
	}
	
	public IEmailToSendService getEmailToSendService() {
		return emailToSendService;
	}
	
	public void setEmailToSendService(IEmailToSendService emailToSendService) {
		this.emailToSendService = emailToSendService;
	}
	
	public IEmailTemplateService getEmailTemplateService() {
		return emailTemplateService;
	}
	
	public void setEmailTemplateService(IEmailTemplateService emailTemplateService) {
		this.emailTemplateService = emailTemplateService;
	}	
	
	@Override 
	@Transactional(readOnly = false)
	public void sendNotification(ScheduleCharter scheduleCharter, String message) {
		EmailTemplate emailTemplate = obtainDefaultWarningTemplate();
		
		if(emailTemplate != null) {
			
			String origenTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_ORIGIN);
			String destinyTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_DESTINY);
			String fullNameTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_FULLNAME);
			String tripDateTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_TRAVEL_DATE);
			String tripNoteTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_NOTICE);
			
			for (Reservation reservation : scheduleCharter.getReservation()) {
				EmailToSend emailToSend = new EmailToSend();
				
				String content = emailTemplate.getTemplate();
				
				content = replaceTagWithText(reservation, message, content,
						origenTag, destinyTag, fullNameTag, tripDateTag,
						tripNoteTag);
				
				emailToSend.setUser(reservation.getUser());
				emailToSend.setMessageContent(content);
				emailToSend.setEmailToSendType(emailTemplate.getEmailToSendType());
				emailToSend.setSubjectContent(emailTemplate.getSubject());
				
				if(reservation.getUser().getDefaultEmail() != null) {
					emailToSendService.add(emailToSend);
				}
			}
		}
	}
	
	
	
	@Transactional(readOnly = true)
	@Override
	public String replaceTextEmailWithVariables(Reservation reservation, String message) {
		
		String emailTemplateText = "";

		if(emailTemplateWarning == null) {
			emailTemplateWarning = obtainDefaultWarningTemplate();
		}
		
		if(emailTemplateWarning != null) {
			emailTemplateText = emailTemplateWarning.getTemplate();
			String origenTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_ORIGIN);
			String destinyTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_DESTINY);
			String fullNameTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_FULLNAME);
			String tripDateTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_TRAVEL_DATE);
			String tripNoteTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_NOTICE);
			
			emailTemplateText = replaceTagWithText(reservation, message, emailTemplateText, origenTag,
					destinyTag, fullNameTag, tripDateTag, tripNoteTag);
		}
		return emailTemplateText;
	}

	private EmailTemplate obtainDefaultWarningTemplate() {
		EmailTemplateFilter emailTemplateFilter = new EmailTemplateFilter();
		emailTemplateFilter.setEmailTemplateTypeDescription(BusinessSettings.EMAIL_TEMPLATE_WARNING);
		EmailTemplate emailTemplate = emailTemplateService.getEmailTemplateByFilter(emailTemplateFilter);
		return emailTemplate;
	}

	private String replaceTagWithText(Reservation reservation, String message,
			String content, String origenTag, String destinyTag,
			String fullNameTag, String tripDateTag, String tripNoteTag) {
		
		String dateTravel =  DateUtil.formatDate(reservation.getScheduleCharter().getSchedule().getDate());
		dateTravel = dateTravel.concat(" ").concat(DateUtil.formatTime(reservation.getScheduleCharter().getSchedule().getTime()));
		
		content = content.replace("{".concat(origenTag).concat("}"), FacesUtil.getMessage(reservation.getScheduleCharter().getTrip().getPlaceOrigin().getDescription()));
		content = content.replace("{".concat(destinyTag).concat("}"), FacesUtil.getMessage(reservation.getScheduleCharter().getTrip().getPlaceDestiny().getDescription()));
		content = content.replace("{".concat(fullNameTag).concat("}"), reservation.getUser().getFullName());
		content = content.replace("{".concat(tripDateTag).concat("}"), dateTravel);
		content = content.replace("{".concat(tripNoteTag).concat("}"), message);
		
		return content;
	}
	
	@Override
	public List<Object[]> getCountReservationByOperator(ReservationFilter reservationFilter) {
		return getReservationDao().getCountReservationByOperator(reservationFilter);
	}
	
	@Override
	public Map<String, String> getReservationStateCombo() {
		HashMap<String, String> combo = new LinkedHashMap<String, String>();
		combo.put(FacesUtil.getMessage("reservationActive"), BusinessSettings.RESERVATION_ACTIVE);
		combo.put(FacesUtil.getMessage("reservationCanceled"), BusinessSettings.RESERVATION_CANCELED);
		return combo;
	}

	@Override
	@Transactional(readOnly = false)
	public void addReservationWithoutEmail(Reservation reservation) {
		reservation.getScheduleCharter().getReservation().add(reservation);
		reservationDao.add(reservation);		
	}
	
}
